package com.ego.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ego.common.constant.ProductConstant;
import com.ego.common.util.PageUtil;
import com.ego.common.vo.PageVo;
import com.ego.product.po.AttrGroup;
import com.ego.product.po.AttrGroupRelation;
import com.ego.product.po.Category;
import com.ego.product.service.AttrGroupRelationService;
import com.ego.product.service.AttrGroupService;
import com.ego.product.service.CategoryService;
import com.ego.product.vo.AttrGroupRelationVo;
import com.ego.common.vo.product.AttrRespVo;
import com.ego.product.vo.AttrSearchVo;
import com.ego.common.vo.product.AttrVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ego.product.dao.AttrDao;
import com.ego.product.po.Attr;
import com.ego.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author KamTang
 * @program: ego
 * @description 商品属性对应实现类
 * @date 2022-11-13 12:56:14
 */
@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, Attr> implements AttrService {

    @Autowired
    private AttrGroupRelationService attrGroupRelationService;
    @Autowired
    private AttrGroupService attrGroupService;
    @Autowired
    private CategoryService categoryService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCascade(AttrVo attrVo) {
        Attr attr = new Attr();
        BeanUtils.copyProperties(attrVo, attr);
        // 1、保存基本数据
        this.save(attr);
        // 2、保存关联关系
        if (attrVo.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attrVo.getAttrGroupId() != null) {
            AttrGroupRelation relationEntity = new AttrGroupRelation();
            relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            relationEntity.setAttrId(attr.getAttrId());
            attrGroupRelationService.save(relationEntity);
        }
    }

    @Override
    public PageVo<AttrRespVo> search(AttrSearchVo search) {
        LambdaQueryWrapper<Attr> query = Wrappers.<Attr>lambdaQuery()
                .eq(StringUtils.isNotEmpty(search.getType()), Attr::getAttrType,
                        "base".equals(search.getType()) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()
                                : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode())
                .eq(search.getCategoryId() != 0, Attr::getCategoryId, search.getCategoryId());
        if (StringUtils.isNotEmpty(search.getKeyword())) {
            query.like(Attr::getAttrName, search.getKeyword())
                    .or().like(Attr::getAttrId, search.getKeyword());
        }

        Page<Attr> page = baseMapper.selectPage(Page.of(search.getPageNum(), search.getPageSize()), query);
        List<Attr> attrEntities = page.getRecords();
        List<AttrRespVo> respVos = attrEntities.stream().map(attr -> {
            AttrRespVo resp = attr.toResp();
            // 设置分类和分组
            if (ProductConstant.AttrEnum.ATTR_TYPE_BASE.getMsg().equals(search.getType())) {
                AttrGroupRelation attrId = attrGroupRelationService
                        .getOne(new QueryWrapper<AttrGroupRelation>()
                                .eq("attr_id", attr.getAttrId()));
                if (attrId != null && attrId.getAttrGroupId() != null) {
                    AttrGroup attrGroup = attrGroupService.getById(attrId.getAttrGroupId());
                    resp.setGroupName(attrGroup.getAttrGroupName());
                }
            }
            Category category = categoryService.getById(attr.getCategoryId());
            if (category != null) {
                resp.setCategoryName(category.getName());
            }
            return resp;
        }).collect(Collectors.toList());
        return PageUtil.toPage(page, respVos);
    }

    @Override
    @Cacheable(value = "attrRespVo", key = "'attrInfo:' + #root.args[0]")
    public AttrRespVo get(Long attrId) {
        Attr attr = this.getById(attrId);
        AttrRespVo resp = attr.toResp();
        if (resp.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 设置分组信息
            AttrGroupRelation attrGroupRelation = attrGroupRelationService.getOne(new QueryWrapper<AttrGroupRelation>()
                    .eq("attr_id", attrId));
            if (attrGroupRelation != null) {
                resp.setAttrGroupId(attrGroupRelation.getAttrGroupId());
                AttrGroup attrGroup = attrGroupService.getById(attrGroupRelation.getAttrGroupId());
                if (attrGroup != null) {
                    resp.setGroupName(attrGroup.getAttrGroupName());
                }
            }
        }

        // 设置分类信息
        Long categoryId = attr.getCategoryId();
        Long[] categoryPath = categoryService.getCategoryPath(categoryId);
        resp.setCategoryPath(categoryPath);
        Category category = categoryService.getById(categoryId);
        if (category != null) {
            resp.setCategoryName(category.getName());
        }
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(AttrVo attrVo) {
        Attr attr = Attr.fromVo(attrVo);
        this.updateById(attr);

        if (attrVo.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 1、修改分组关联
            AttrGroupRelation relationEntity = new AttrGroupRelation();
            relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            relationEntity.setAttrId(attrVo.getAttrId());

            long count = attrGroupRelationService.count(new QueryWrapper<AttrGroupRelation>()
                    .eq("attr_id", attrVo.getAttrId()));
            // 原来就有数据就执行更新操作，否则执行添加操作。
            if (count > 0) {
                attrGroupRelationService.update(relationEntity, new UpdateWrapper<AttrGroupRelation>()
                        .eq("attr_id", attrVo.getAttrId()));
            } else {
                attrGroupRelationService.save(relationEntity);
            }
        }
    }

    @Override
    public List<Attr> getAttrRelation(List<Long> attrGroupIds) {
        return getAttrEntities(attrGroupIds);
    }

    @Override
    public PageVo<Attr> getNoRelationAttr(AttrGroupRelationVo vo) {
        // 当前分组只能关联自己所属的分类里面的所有属性
        AttrGroup attrGroup = attrGroupService.getById(vo.getAttrGroupId());
        Long categoryId = attrGroup.getCategoryId();

        // 当前分组只能关联别的分组没有引用的属性
        // 当前分类下的其他分组
        List<AttrGroup> attrGroups = attrGroupService
                .list(new QueryWrapper<AttrGroup>().eq("category_id", categoryId));
        List<Long> attrGroupIds = attrGroups.stream().map(AttrGroup::getAttrGroupId).collect(Collectors.toList());

        // 这些分组关联的属性
        List<AttrGroupRelation> attrGroupRelations = attrGroupRelationService
                .list(new QueryWrapper<AttrGroupRelation>().in("attr_group_id", attrGroupIds));
        List<Long> attrIds = attrGroupRelations.stream().map(AttrGroupRelation::getAttrId).collect(Collectors.toList());

        // 从当前分类的所有属性中移除这些属性
        QueryWrapper<Attr> query = new QueryWrapper<Attr>().eq("category_id", categoryId)
                .eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        if (attrIds.size() > 0) {
            query.notIn("attr_id", attrIds);
        }
        String keyword = vo.getKeyword();
        if (StringUtils.isNotEmpty(keyword)) {
            query.and((i) -> i.eq("attr_id", keyword).or().like("attr_name", keyword));
        }
        Page<Attr> page = baseMapper.selectPage(Page.of(vo.getPageNum(), vo.getPageSize()), query);
        return PageUtil.toPage(page);
    }

    @Override
    public List<Attr> getByGroupIds(List<Long> attrGroupIds) {
        return getAttrEntities(attrGroupIds);
    }

    @Override
    public List<Long> getRetrievableId(List<Long> attrIds) {
        return this.baseMapper.getRetrievableId(attrIds);
    }

    private List<Attr> getAttrEntities(List<Long> attrGroupIds) {
        List<AttrGroupRelation> attrGroupRelations = attrGroupRelationService
                .list(new QueryWrapper<AttrGroupRelation>().in("attr_group_id", attrGroupIds));
        List<Long> attrIds = attrGroupRelations.stream().map(AttrGroupRelation::getAttrId).collect(Collectors.toList());
        if (attrIds.size() == 0) {
            return null;
        }
        return this.listByIds(attrIds);
    }
}
